package com.hc.likelistenmusic.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;

import com.hc.likelistenmusic.R;


public class RoundRotateProgressView extends View {
    Paint mPaint;
    Path mPath;
    Matrix mMatrix;
    Bitmap mSrcBitmap;
    ValueAnimator mValueAnimator;
    float mRotateDegree;
    float mRingStartDegree;
    float mRingWidth;
    int mRingDrawColor;
    int mRingBgColor;
    long mDuration;
    int mScreenShortestBorder;
    int mBorderSize;
    int mCurrentProgress = 0;
    int mTotalProgress = 1;

    public RoundRotateProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundRotateProgressView);
        mRingStartDegree = typedArray.getFloat(R.styleable.RoundRotateProgressView_ringStartDegree, -90f);
        mRingWidth = typedArray.getDimension(R.styleable.RoundRotateProgressView_ringWidth, dp2px(context, 2));
        mRingDrawColor = typedArray.getColor(R.styleable.RoundRotateProgressView_ringDrawColor, Color.WHITE);
        mRingBgColor = typedArray.getColor(R.styleable.RoundRotateProgressView_ringBgColor, Color.GRAY);
        mDuration = typedArray.getInteger(R.styleable.RoundRotateProgressView_rotateDuration, 6000);
        mScreenShortestBorder = getScreenPx(context);
        mMatrix = new Matrix();
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(mRingWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        ViewGroup.LayoutParams layoutParams = getLayoutParams();
        int width = layoutParams.width;
        int height = layoutParams.height;
        if (width == 0 || height == 0) {
            throw new RuntimeException("you can not set layout_width or layout_height value = 0");
        }
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (!(widthMode == MeasureSpec.EXACTLY) || !(heightMode == MeasureSpec.EXACTLY)) {
            throw new RuntimeException("you can not set layout_width or layout_height value = wrap_content");
        }
        int borderSize = Math.min(Math.min(widthSize, heightSize), mScreenShortestBorder);
        setMeasuredDimension(borderSize, borderSize);
    }

    private int dp2px(Context context, float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    public int getScreenPx(Context context) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        if (displayMetrics.widthPixels <= displayMetrics.heightPixels) {
            return displayMetrics.widthPixels;
        } else {
            return displayMetrics.heightPixels;
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mValueAnimator == null) {
            mValueAnimator = ValueAnimator.ofFloat(0, 360);
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mRotateDegree = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            mValueAnimator.setInterpolator(new LinearInterpolator());
            mValueAnimator.setDuration(mDuration);
            mValueAnimator.setRepeatCount(-1);
            mValueAnimator.setRepeatMode(ValueAnimator.RESTART);
        }
        mBorderSize = w;
        mPath.addCircle(mBorderSize / 2, mBorderSize / 2, mBorderSize / 2 - mRingWidth, Path.Direction.CW);
        scaleMatrix((int) (mBorderSize - mRingWidth));
    }

    public void setBimap(Bitmap bitmap) {
        mSrcBitmap = bitmap;
        scaleMatrix((int) (mBorderSize - mRingWidth));
        postInvalidate();
    }

    public void setProgress(int currentProgress, int totalProgress) {
        if (totalProgress < 1) {
            totalProgress = 1;
        }
        if (currentProgress <= totalProgress) {
            mCurrentProgress = currentProgress;
            mTotalProgress = totalProgress;
            postInvalidate();
        }
    }

    public void resetProgress() {
        mCurrentProgress = 0;
        mTotalProgress = 1;
        postInvalidate();
    }

    public void startAnim() {
        if (mValueAnimator != null) {
            if(!mValueAnimator.isStarted()){
                mValueAnimator.start();
            }else {
                if(mValueAnimator.isPaused()){
                    mValueAnimator.resume();
                }
            }
        }
    }

    public void pauseAnim() {
        if (mValueAnimator != null) {
            mValueAnimator.pause();
        }
    }

    public void endAnim() {
        if (mValueAnimator != null) {
            mValueAnimator.end();
        }
    }

    public void error(){
        if(mValueAnimator !=null){
            mValueAnimator.end();
        }
        resetProgress();
    }

    private void scaleMatrix(int total) {
        if (mSrcBitmap != null) {
            mMatrix.reset();
            int min = Math.min(mSrcBitmap.getWidth(), mSrcBitmap.getHeight());
            float scale = (float) total / min;
            mMatrix.setScale(scale, scale);
        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        if (mSrcBitmap != null) {
            canvas.save();
            canvas.rotate(mRotateDegree, mBorderSize / 2, mBorderSize / 2);
            canvas.clipPath(mPath);
            canvas.drawBitmap(mSrcBitmap, mMatrix, null);
            canvas.restore();
        }
        float halfRingWidth = mRingWidth / 2;
        mPaint.setColor(mRingBgColor);
        mPaint.setStrokeWidth(mRingWidth);
        canvas.drawArc(halfRingWidth, halfRingWidth, mBorderSize - halfRingWidth, mBorderSize - halfRingWidth, 0, 360, false, mPaint);
        if (mCurrentProgress > 0) {
            float degree = ((float) mCurrentProgress / mTotalProgress) * 360;
            mPaint.setColor(mRingDrawColor);
            mPaint.setStrokeWidth(mRingWidth);
            canvas.drawArc(halfRingWidth, halfRingWidth, mBorderSize - halfRingWidth, mBorderSize - halfRingWidth, mRingStartDegree, degree, false, mPaint);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mSrcBitmap != null) {
            mSrcBitmap.recycle();
            mSrcBitmap = null;
        }
        if (mValueAnimator != null) {
            mValueAnimator.removeAllListeners();
            mValueAnimator.removeAllUpdateListeners();
            mValueAnimator.cancel();
            mValueAnimator = null;
        }
    }
}
